#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include <stdint.h>
#include "zuc.h"
#include "endian.h"

// void memxor(void *r, const void *a, const void *b, size_t len)
// {
// 	uint8_t *pr = r;
// 	const uint8_t *pa = a;
// 	const uint8_t *pb = b;
// 	size_t i;
// 	for (i = 0; i < len; i++) {
// 		pr[i] = pa[i] ^ pb[i];
// 	}
// }
int showbit(char *dd, int length)
{                                     //显示十六进制数据
    unsigned short int data[256 * 4]; // 2

    memset(data, 0, length);
    memcpy(data, dd, length);

    int i = 0;
    for (i = 0; i < length / 2; i++)
    {
        printf("%04x", data[i]);
    }
    if (length % 2 != 0)
    {
        printf("%02x", data[length / 2]);
    }
    printf("\n");
}

int main()
{
    // key ,iv and segment_size are only three shared data between client and server
    unsigned char key[16] = {
        0x31,
        0x32,
        0x33,
        0x34,
        0x35,
        0x36,
        0x37,
        0x38,
        0x31,
        0x32,
        0x33,
        0x34,
        0x35,
        0x36,
        0x37,
        0x38,
    };
    unsigned char iv[16] = {
        0x31,
        0x32,
        0x33,
        0x34,
        0x35,
        0x36,
        0x37,
        0x38,
        0x31,
        0x32,
        0x33,
        0x34,
        0x35,
        0x36,
        0x37,
        0x38,
    };
    int segment_size=256;

    // client side define 
    
    unsigned char plaintext[1024] ;
    int client_offset=0;
    int client_N_S=0;
    unsigned char inbuf[256]; 
    ZUC_STATE zuc_state = {{0}};
    // assume there are 10 data send; 
    unsigned int cryptblock[10] = {10,10,5,15,30,70,150,100,60,40};

    // server side define
    unsigned char deciphertext[1024];
    int server_offset=0;
    int server_N_S=0;
    unsigned char outbuf[256]; 
    ZUC_STATE zuc_state1 = {{0}};

    //	temp variable, 
    int i,j;
    unsigned char keybuf[256];

    // emulate the transfer action
    unsigned char transbuf[256];
	
    // client side: init the plain text

   for(i=0;i<1024;i++)
   {
	inbuf[i]=i%256;
   }	

   
    // client side : init client's zuc state	
    zuc_init(&zuc_state, key, iv);

    // server side: init server's zuc state
    zuc_init(&zuc_state1, key, iv);

    
    // crypt/decrypt ten times	
    for(i=0;i<10;i++)
    { 
    	// client side: build input data, first byte is cryptblock[i]
		
	printf("client side:\n");
    	memset(inbuf, 0, 256);
	inbuf[0]=cryptblock[i];
	memcpy(inbuf+1,plaintext+client_offset,cryptblock[i]);

	client_offset+=cryptblock[i];
	client_N_S++;
    	zuc_generate_keystream(&zuc_state, segment_size/4,keybuf);

    	showbit(inbuf, cryptblock[i]+1);

	transbuf[0]=inbuf[0];
    	gmssl_memxor(transbuf+1, inbuf+1, keybuf, inbuf[0]);

    	showbit(transbuf,cryptblock[i]+1);


	// server side: receive transfer data and decipher it

	printf("server side:\n");
	server_N_S++;
    	zuc_generate_keystream(&zuc_state1, segment_size/4,keybuf);
	outbuf[0]=transbuf[0];
	gmssl_memxor(outbuf+1,transbuf+1,keybuf,transbuf[0]);
    	showbit(outbuf,cryptblock[i]+1);
	memcpy(deciphertext+server_offset,outbuf,outbuf[0]);
	server_offset+=outbuf[0];
    	printf("\n");
    }
    return 0;
}
